package com.level.restful.util.httpLogUtil;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.apache.commons.lang.ArrayUtils;
import org.apache.ibatis.javassist.*;
import org.apache.ibatis.javassist.bytecode.CodeAttribute;
import org.apache.ibatis.javassist.bytecode.LocalVariableAttribute;
import org.apache.ibatis.javassist.bytecode.MethodInfo;
import org.aspectj.lang.JoinPoint;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;

/**
 * @author tqf
 *
 */
public class RequestUtil {
    /**
     * 获取切入点信息
     * @param joinPoint
     * @return
     */
    public static Map<String,Object> getJoinPointInfoMap(JoinPoint joinPoint) throws ClassException, NotFindException {
        Map<String,Object> joinPointInfo = new HashMap<>();
        String classPath = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        joinPointInfo.put("classPath",classPath);
        joinPointInfo.put("methodName",methodName);

        Class<?> clazz = null;
        CtMethod ctMethod = null;
        LocalVariableAttribute attr = null;
        int length = 0;
        int pos = 0;

        try{
            clazz = Class.forName(classPath);
            String clazzName = clazz.getName();
            ClassPool pool = ClassPool.getDefault();
            ClassPath classClassPath = new ClassClassPath(clazz);
            pool.insertClassPath(classClassPath);
            CtClass ctClass = pool.getCtClass(clazzName);
            ctMethod = ctClass.getDeclaredMethod(methodName);
            MethodInfo methodInfo = ctMethod.getMethodInfo();
            CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
            attr = (LocalVariableAttribute)codeAttribute.getAttribute(LocalVariableAttribute.tag);
            if(attr == null ){
                return joinPointInfo;
            }

            length = ctMethod.getParameterTypes().length;
            pos = Modifier.isStatic(ctMethod.getModifiers()) ? 0 : 1;

        }catch (ClassNotFoundException e){
            throw new ClassException("获取类实例失败");
        }catch (NotFoundException e){
            throw new NotFindException("未找到参数类型");
        }

        Map<String,Object> paramMap = new HashMap<>();
        Object [] paramsArgsValues = joinPoint.getArgs();
        String [] paramsArgsNames = new String[length];
        for(int i = 0; i < length; i++){
            paramsArgsNames[i] = attr.variableName(i+pos);
            String paramsArgsName = attr.variableName(i+pos);
            if("request".equalsIgnoreCase(paramsArgsName) || "response".equalsIgnoreCase(paramsArgsName) ||
                    "session".equalsIgnoreCase(paramsArgsName)){
                break;
            }
            if (paramsArgsValues[i] instanceof ServletRequest || paramsArgsValues[i] instanceof ServletResponse
                    || paramsArgsValues[i] instanceof MultipartFile) {
                continue;
            }

            Object paramsArgsValue = paramsArgsValues[i];
            paramMap.put(paramsArgsName,paramsArgsValue);

        }
        joinPointInfo.put("paramMap", JSON.toJSONString(paramMap, SerializerFeature.DisableCircularReferenceDetect,
                SerializerFeature.WriteMapNullValue));
        return joinPointInfo;
    }

    /**
     * 获取请求IP
     * @return
     */
    public static String getRequestIp(HttpServletRequest request) throws RequestException {
        if(request == null){
            throw new RequestException("HttpServletRequest对象为空");
        }
        String ip = request.getHeader("x-forworded-for");
        if(ip == null || ip.trim() == "" || "unknown".equalsIgnoreCase(ip)){
            ip = request.getHeader("Proxy-Client-IP");
        }

        if(ip == null || ip.trim() == "" || "unknown".equalsIgnoreCase(ip)){
            ip = request.getHeader("Wl-Proxy-Client-IP");
        }
        if(ip == null || ip.trim() == "" || "unknown".equalsIgnoreCase(ip)){
            ip = request.getRemoteAddr();
        }

        final String [] arr = ip.split(",");
        for(final String s : arr){
            if(!"unknown".equalsIgnoreCase(ip)){
                ip = s;
                break;
            }
        }
        return ip;
    }

    /**
     * 获取请求方式：普通请求、Ajax请求
     * @param request
     * @return
     */
    public static Integer getRequestType(HttpServletRequest request) throws RequestException {
        if(request == null){
            throw new RequestException("HttpServletRequest对象为空");
        }
        String xRequestWith = request.getHeader("X-Requested-With");
        return xRequestWith == null ? 1 : 2;
    }

    public static <T> Stream<T> streamOf(T[] array) {
        return ArrayUtils.isEmpty(array) ? Stream.empty() : Arrays.asList(array).stream();
    }
}
